/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.google.code.peersim.pastry.controls;

import com.google.code.peersim.pastry.protocol.PastryId;
import com.google.code.peersim.pastry.protocol.PastryNode;
import com.google.code.peersim.pastry.protocol.PastryResource;
import java.util.LinkedList;
import java.util.Queue;

/**
 * This static class works as a coordination point between a {@link PastryResourceAssigner}
 * and a {@link PastryResourceFinder}. The former creates {@link PastryResource}s leveraging
 * on this static class, and as soon as a resource gets assigned to its final destination it
 * is also stored in this static class instance.<br>
 * On the other side, a {@link PastryResourceFinder} periodically asks this class instance for
 * newly assigned resources to look for in the pastry network.
 *
 * @author frusso
 * @version 0.1
 * @since 0.1
 */
public class AssignedResources {

  /**
   * The queue of resources actually assigned to {@link PastryNode}s.
   */
  private static final Queue<PastryId> assignedIds = new LinkedList<PastryId>();

  /**
   * Once a resource has been assigned to a {@link PastryNode}, its {@link PastryId}
   * has to be stored here in by means of this method.
   *
   * @param res The resource that has been delivered to its final destination
   */
  public static void addAssignedResource(PastryResource<?> res) {
    assignedIds.add(res.getResourceId());
  }

  /**
   * Factory method for creating brand new {@link PastryResource}s.
   *
   * @param <T> The resource payload actual type
   * @param payload The payload
   * @return The created {@link PastryResource}
   */
  public static <T> PastryResource<T> createResource(T payload) {
    PastryResource<T> res = new PastryResource(payload);
    return res;
  }

  /**
   * Peeks the first available {@link PastryId}, if any. Should there be no
   * available resources, {@code null} is returned.
   *
   * @return A valid {@link PastryId} of an assigned resource or {@code null}
   * if none is available
   */
  public static PastryId peekAssignedId() {
    if(!assignedIds.isEmpty())
      return assignedIds.peek();
    else
      return null;
  }

  /**
   * Removes the first (top of the queue) available {@link PastryId} if any, and
   * returns it, otherwise {@code null} is returned.
   *
   * @return The top of the {@link PastryId} queue, or {@code null}
   */
  public static PastryId remove() {
    if(!assignedIds.isEmpty())
      return assignedIds.remove();
    else
      return null;
  }

  /**
   * Returns the number of already assigned {@link PastryResource}s.
   *
   * @return The number of already assigned {@link PastryResource}s
   */
  public static int size() {
    return assignedIds.size();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return assignedIds.toString();
  }
}